home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / ~Solutions Submitted / Problem 02 - Hearn / Solution.cp < prev   
Encoding:
Text File  |  1998-06-19  |  4.9 KB  |  280 lines  |  [TEXT/CWIE]

  1. /*
  2. Problem 02 - Hower of Tanoi
  3.  
  4. This problem is to solve a variant of the Tower of Hanoi puzzle.  You remember
  5. the Tower of Hanoi, a board with three pegs, one of which has N disks of size
  6. 1, 2, 3, ... N, with the smallest disk at the top.  In the standard puzzle, the
  7. goal is to move all of the disks from one peg to another peg, by repeatedly
  8. moving a disk from the top of one peg to another peg without ever placing a
  9. larger disk on top of a smaller disk.
  10.  
  11. In our Hower of Tanoi problem, the objective and the constraints are the same,
  12. except that the disks on the first peg are initially in random order. You can
  13. still only move a smaller disk onto a larger disk.
  14.  
  15. Your objective is output the moves required to place all the disks on peg 3 in
  16. order with the smallest disk at the top.  
  17.  
  18. Input specification
  19.  
  20. The first line of the input file contains an integer M, M<1000, the number of
  21. disks in the problem.  The next M lines contain the numbers 1 .. M, one number
  22. per line, randomly ordered, where the first number is the size of the top disk
  23. on peg 1, the second number is the size of the 2nd disk from the top, etc.
  24.  
  25. Output specification
  26.  
  27. The output is a sequence of lines, each representing a single move,  consisting
  28. of the source peg number followed by a comma (',') followed by the destination
  29. peg number, followed by a return character.
  30.  
  31. Sample input
  32.  
  33. 2
  34. 2
  35. 1
  36.  
  37. Sample output
  38.  
  39. 1,3
  40. 1,3
  41. */
  42.  
  43. #include "Solution.h"
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47.  
  48. // Fill in your solution and then submit this folder
  49.  
  50. // Team Name: Bob Hearn
  51.  
  52. long Disks;
  53.  
  54. #define MAXDISKS    1000
  55.  
  56. struct Towers
  57. {
  58.     int tower[3][MAXDISKS];
  59.     int top[3];
  60. };
  61.  
  62. Towers TheTowers;
  63.  
  64. struct Move
  65. {
  66.     short from, to;
  67. };
  68.  
  69. const long MaxMoves = 10000;
  70.  
  71. struct Move Moves[MaxMoves];
  72. long NumMoves;
  73.  
  74. long GetNumber(short rn);
  75.  
  76. long GetNumber(short rn)
  77. {
  78. long size = 1;
  79. char c;
  80. long number = 0;
  81. OSErr err;
  82.  
  83.     while (1)
  84.     {
  85.         err = FSRead(rn, &size, &c);
  86.         
  87.         if (err || c == '\r')
  88.             break;
  89.             
  90.         number *= 10;
  91.         number += c - '0';
  92.     }
  93.  
  94.     return number;
  95. }
  96.  
  97. void WriteNumber(short rn, long num);
  98. void WriteChar(short rn, char c);
  99.  
  100. void WriteNumber(short rn, long num)
  101. {
  102.     if (num > 9)
  103.         WriteNumber(rn, num / 10);
  104.         
  105.     WriteChar(rn, num + '0');
  106. }
  107.  
  108. void WriteChar(short rn, char c)
  109. {
  110. long size = 1;
  111.  
  112.         FSWrite( rn, &size, &c );
  113. }
  114.  
  115.  
  116. short Find(long disk);
  117. short GoodState(long disk);
  118. short Almost(long disk);
  119. short Top(short tower);
  120. void DoMove(short from, short to);
  121. void RandMove();
  122.  
  123. pascal OSErr HowerOfTanoi( const FSSpec* infile, const FSSpec* outfile )
  124. {
  125. short rn;
  126. OSErr err;
  127. long x;
  128. short tower;
  129.  
  130.     srand(TickCount());
  131.     
  132.     err = FSpOpenDF( infile, fsRdPerm, &rn );
  133.  
  134.     Disks = GetNumber(rn);
  135.     
  136.     for (x = 0; x < Disks; ++x)
  137.         TheTowers.tower[0][Disks - x - 1] = GetNumber(rn);
  138.     
  139.     TheTowers.top[0] = Disks;
  140.     TheTowers.top[1] = 0;
  141.     TheTowers.top[2] = 0;
  142.     
  143.     FSClose(rn);
  144.     
  145.     NumMoves = 0;
  146.     
  147.     for (x = Disks; x > 0; --x)
  148.     {
  149.         tower = Find(x);
  150.         DoMove(tower, 3);
  151.     }
  152.     
  153.     err = FSpCreate( outfile, 'CWIE', 'TEXT', 0 );
  154.     err = FSpOpenDF( outfile, fsWrPerm, &rn );    
  155.  
  156.     for (x = 0; x < NumMoves; ++x)
  157.     {
  158.         WriteNumber(rn, Moves[x].from);
  159.         WriteChar(rn, ',');
  160.         WriteNumber(rn, Moves[x].to);
  161.         WriteChar(rn, '\r');
  162. //        fprintf(rn, "%d,%d\n", Moves[x].from, Moves[x].to);
  163.     }
  164.  
  165.     FSClose(rn);
  166.     
  167.     return noErr;
  168. }
  169.  
  170. Towers OldTowers;
  171.  
  172. short Find(long disk)
  173. {
  174. long oldmoves = NumMoves;
  175. long x, y;
  176. short tower;
  177. long max = 100;
  178.  
  179.     OldTowers = TheTowers;
  180.     
  181.     while (++max)
  182.     {
  183.         for (x = 0; x < max; ++x)
  184.         {
  185.             if (tower = GoodState(disk))
  186.                 return tower;
  187.             
  188.         //    if (tower = Almost(disk))
  189.         //    {
  190.         //        DoMove(tower, 3 - tower);
  191.         //        
  192.         //        return tower;
  193.         //    }
  194.             
  195.             RandMove();
  196.         }
  197.             
  198.     //    TheTowers = OldTowers;
  199.         
  200.         for (x = 0; x < 3; ++x)
  201.         {
  202.             TheTowers.top[x] = OldTowers.top[x];
  203.             for (y = 0; y < TheTowers.top[x]; ++y)
  204.                 TheTowers.tower[x][y] = OldTowers.tower[x][y];
  205.         }
  206.         
  207.         NumMoves = oldmoves;
  208.         
  209. //        printf("\nPop to move %d\n\n", NumMoves);
  210.     }
  211.     
  212.     return tower;
  213. }
  214.  
  215. short GoodState(long disk)
  216. {
  217.     if (Top(3) == disk + 1)
  218.     {
  219.         if (Top(1) == disk)
  220.             return 1; 
  221.         if (Top(2) == disk)
  222.             return 2;
  223.     }
  224.     
  225.     return 0;
  226. }
  227.  
  228. short Almost(long disk)
  229. {
  230.     if (Top(3) == disk + 1)
  231.     {
  232.         if (Top(1) > Top(2))
  233.         {
  234.             if (TheTowers.top[1] > 1 && TheTowers.tower[1][TheTowers.top[1] - 2] == disk)
  235.                 return 2;
  236.         }
  237.         else
  238.         {
  239.             if (TheTowers.top[0] > 1 && TheTowers.tower[0][TheTowers.top[0] - 2] == disk)
  240.                 return 1;
  241.         }
  242.     }
  243.     
  244.     return 0;
  245. }
  246.  
  247. void DoMove(short from, short to)
  248. {
  249. //    printf("%d: move %d to %d\n", NumMoves, from, to);
  250.  
  251.     TheTowers.tower[to - 1][TheTowers.top[to - 1]++] = TheTowers.tower[from - 1][--TheTowers.top[from - 1]];
  252.     Moves[NumMoves].from = from;
  253.     Moves[NumMoves++].to = to;
  254. }
  255.  
  256. short Top(short tower)
  257. {
  258.     if (TheTowers.top[tower - 1])
  259.         return TheTowers.tower[tower - 1][TheTowers.top[tower - 1] - 1];
  260.         
  261.     return Disks + 1;
  262. }
  263.  
  264. void RandMove()
  265. {
  266. short from, to;
  267.  
  268.     while (1)
  269.     {
  270.         from = (((unsigned) rand()) % 3) + 1;
  271.         to = (((unsigned) rand()) % 3) + 1;
  272.         
  273.         if (TheTowers.top[from - 1] && Top(to) > Top(from))
  274.         {
  275.             DoMove(from, to);
  276.             return;
  277.         }
  278.     }
  279. }
  280.